\myparagraph{\NonOptimizing MSVC}

Вот что выдал MSVC 2010:

\lstinputlisting[caption=\NonOptimizing MSVC 2010,style=customasmx86]{patterns/12_FPU/3_comparison/x86/MSVC/MSVC_RU.asm}

\myindex{x86!\Instructions!FLD}
Итак, \FLD загружает \GTT{\_b} в регистр \ST{0}.

\label{Czero_etc}
\newcommand{\Czero}{\GTT{C0}\xspace}
\newcommand{\Ctwo}{\GTT{C2}\xspace}
\newcommand{\Cthree}{\GTT{C3}\xspace}
\newcommand{\CThreeBits}{\Cthree/\Ctwo/\Czero}

\myindex{x86!\Instructions!FCOMP}
\FCOMP сравнивает содержимое \ST{0} с тем, что лежит в \GTT{\_a} и выставляет биты \CThreeBits в 
регистре статуса FPU. Это 16-битный регистр отражающий текущее состояние FPU.

После этого инструкция \FCOMP также выдергивает одно значение из стека. 
Это отличает её от \FCOM, которая просто сравнивает значения, оставляя стек в таком же состоянии.

К сожалению, у процессоров до Intel P6
\footnote{Intel P6 это Pentium Pro, Pentium II, и последующие модели} нет инструкций условного перехода,
проверяющих биты \CThreeBits.
Возможно, так сложилось исторически (вспомните о том, что FPU когда-то был вообще отдельным чипом).\\
А у Intel P6 появились инструкции \FCOMI/\FCOMIP/\FUCOMI/\FUCOMIP, делающие то же самое, 
только напрямую модифицирующие флаги \ZF/\PF/\CF.

\myindex{x86!\Instructions!FNSTSW}
Так что \FNSTSW копирует содержимое регистра статуса в \AX. 
Биты \CThreeBits занимают позиции, 
соответственно, 14, 10, 8. В этих позициях они и остаются в регистре \AX, 
и все они расположены в старшей части регистра~--- \AH.

\begin{itemize}
\item Если $b>a$ в нашем случае, то биты \CThreeBits должны быть выставлены так: 0, 0, 0.
\item Если $a>b$, то биты будут выставлены: 0, 0, 1.
\item Если $a=b$, то биты будут выставлены так: 1, 0, 0.
\item Если результат не определен (в случае ошибки), то биты будут выставлены так: 1, 1, 1.
\end{itemize}
% TODO: table here?

Вот как биты \CThreeBits расположены в регистре \AX:

\input{C3_in_AX}

Вот как биты \CThreeBits расположены в регистре \AH:

\input{C3_in_AH}

После исполнения \INS{test ah, 5}\footnote{5=101b} % FIXME: subscript here!
будут учтены только биты \Czero и \Ctwo (на позициях 0 и 2), остальные просто проигнорированы.

\label{parity_flag}
\myindex{x86!\Registers!\Flags!Флаг четности}
Теперь немного о \IT{parity flag}\footnote{флаг четности}. 
Ещё один замечательный рудимент эпохи.

Этот флаг выставляется в 1 если количество единиц в последнем результате четно. 
И в 0 если нечетно.

Заглянем в Wikipedia\footnote{\href{http://go.yurichev.com/17131}{wikipedia.org/wiki/Parity\_flag}}:

\begin{framed}
\begin{quotation}
One common reason to test the parity flag actually has nothing to do with parity. The FPU has four condition flags 
(C0 to C3), but they cannot be tested directly, and must instead be first copied to the flags register. 
When this happens, C0 is placed in the carry flag, C2 in the parity flag and C3 in the zero flag. 
The C2 flag is set when e.g. incomparable floating point values (NaN or unsupported format) are compared 
with the FUCOM instructions.
\end{quotation}
\end{framed}

Как упоминается в Wikipedia, флаг четности иногда используется в FPU-коде и сейчас мы увидим как.

\myindex{x86!\Instructions!JP}
Флаг \PF будет выставлен в 1, если \Czero и \Ctwo оба 1 или оба 0. 
И тогда сработает последующий \JP (\IT{jump if PF==1}). 
Если мы вернемся чуть назад и посмотрим значения \CThreeBits 
для разных вариантов, то увидим, что условный переход \JP сработает в двух случаях: если $b>a$ или если $a=b$ 
(ведь бит \Cthree перестал учитываться после исполнения \INS{test ah, 5}).

Дальше всё просто. Если условный переход сработал, то \FLD загрузит значение \INS{\_b} в \ST{0}, 
а если не сработал, то загрузится \GTT{\_a} и произойдет выход из функции.

\mysubparagraph{А как же проверка флага \Ctwo?}

Флаг \Ctwo включается в случае ошибки (\gls{NaN}, итд.), но наш код его не проверяет.

Если программисту нужно знать, не произошла ли FPU-ошибка, он должен позаботиться об этом
дополнительно, добавив соответствующие проверки.

\input{patterns/12_FPU/3_comparison/x86/MSVC/olly_RU.tex}
